import type { UploadFile } from '@/views/modules/system/folder/data/types';
import { nanoid } from 'nanoid';

export interface UploadType {
  accept?: string;
  multiple?: boolean;
  size?: number;
  isFolder?: boolean;
}

export const useUploadFile = (config: UploadType) => {
  const createInput = (config: UploadType) => {
    const input = document.createElement('input');
    input.hidden = true;
    input.type = 'file';

    if (config.isFolder) {
      input.webkitdirectory = config.isFolder;
      input.multiple = true;
    } else {
      input.multiple = config.multiple ?? false;
      input.accept = config.accept ?? '';
    }
    input.click();
    return input;
  };
  const input = createInput(config);
  return new Promise<Array<File>>(res => {
    input.onchange = () => {
      const { files } = input;
      if (!files) return;
      if (files.length === 0) return;
      let fileList = Array.from(files);
      fileList = fileList.filter(item => {
        if (!config.size) {
          config.size = 500 * 1024;
        }
        if (item.size > config.size * 1024) {
          return null;
        }
        return item;
      });
      res(fileList);
    };
  });
};

/* 文件转base64 */
export const toBase64 = (file: File) => {
  const reader = new FileReader();
  reader.readAsDataURL(file);
  return new Promise<string>(res => {
    reader.onload = () => {
      res(reader.result as string);
    };
  });
};

/* 文件转文本 */
export const toText = (file: File) => {
  const reader = new FileReader();
  reader.readAsText(file);
  return new Promise<string>(res => {
    reader.onload = () => {
      res(reader.result as string);
    };
  });
};

/* 文件转二进制 */
export const toBinary = (file: File): Promise<ArrayBuffer | any> => {
  const reader = new FileReader();
  reader.readAsArrayBuffer(file);
  return new Promise(res => {
    reader.onload = () => {
      const binaryData = reader.result;
      res(binaryData);
    };
  });
};

// type:文件类型
export const base64ToBlob = (urlData: string, type: string) => {
  const arr = urlData.split(',');
  const array = arr[0].match(/:(.*?);/);
  const mime = (array && array.length > 1 ? array[1] : type) || type;
  // 去掉url的头，并转化为byte
  const bytes = window.atob(arr[1]);
  // 处理异常,将ascii码小于0的转换为大于0
  const ab = new ArrayBuffer(bytes.length);
  // 生成视图（直接针对内存）：8位无符号整数，长度1个字节
  const ia = new Uint8Array(ab);
  // eslint-disable-next-line no-plusplus
  for (let i = 0; i < bytes.length; i++) {
    ia[i] = bytes.charCodeAt(i);
  }
  return new Blob([ab], {
    type: mime,
  });
};

/* 获取文件拓展名 */
export const getFileExtension = (filename: string) => {
  const lastDotIndex = filename.lastIndexOf('.');
  if (lastDotIndex === -1 || lastDotIndex === 0) {
    return '';
  }
  // 返回从"."之后到字符串结束的部分
  return filename.substring(lastDotIndex + 1);
};

export const arrayBufferToFile = (
  arrayBuffer: ArrayBuffer,
  fileName: string = nanoid().slice(0, 8),
) => {
  const blob = new Blob([arrayBuffer]);
  const file = new File([blob], fileName);
  return file;
};

export const base64toFile = (base64String: string, filename: string = nanoid()): File => {
  const arr = base64String.split(',');
  const fileType = arr[0].match(/:(.*?);/)?.[1];
  const bstr = atob(arr[1]);
  let n = bstr.length;
  const u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new File([u8arr], filename, { type: fileType });
};

export const blobToBase64 = (blob: Blob): Promise<string> => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onerror = reject;
    reader.onload = () => {
      resolve(reader.result as string);
    };
    reader.readAsDataURL(blob);
  });
};
/**
 * @description: BLOB转URL
 * @param {Blob} blob
 */
export const blobToUrl = (blob: Blob) => {
  return URL.createObjectURL(blob);
};

export const isBase64 = (input: string): boolean => {
  const base64Regex = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
  return base64Regex.test(input);
};

/* 预览远程链接文件 */
export const viewRemoteFile = async (path: string) => {
  // 发起GET请求以获取远程文件
  const response = await fetch(path);

  if (!response.ok) {
    throw new Error(`Failed to fetch file at ${path}: ${response.statusText}`);
  }

  // 根据Content-Type判断文件类型
  const contentType = response.headers.get('content-type');
  if (!contentType) {
    throw new Error('Failed to determine content type.');
  }

  // 将响应体转换为Blob对象
  return await response.blob();
};

/**
 * @description: 下载导出文件
 * @param {Blob} blob
 * @param {string} fileName
 */
export const downloadExportFile = (blob: Blob, fileName: string): void => {
  const downloadElement = document.createElement('a');
  let href: any = blob;
  if (typeof blob === 'string') {
    downloadElement.target = '_blank';
  } else {
    href = window.URL.createObjectURL(blob); // 创建下载的链接
  }
  downloadElement.href = href;
  downloadElement.download = `${fileName}`; // 下载后文件名
  document.body.appendChild(downloadElement);
  downloadElement.click(); // 触发点击下载
  document.body.removeChild(downloadElement); // 下载完成移除元素
  if (typeof blob !== 'string') {
    window.URL.revokeObjectURL(href); // 释放掉blob对象
  }
};
/**
 * @description:
 *    仅处理拖拽到浏览器中的文件
 * @param {DragEvent} e 拖拽事件
 * @return {UploadFile} 统一转换接口
 */
export const fileConversion = async (e: DragEvent): Promise<UploadFile[]> => {
  e.preventDefault();
  const dataTransfer = e.dataTransfer;
  let files: UploadFile[] = [];

  const traverseFileTree = async (item: any, path = '') => {
    return new Promise<void>((resolve, reject) => {
      if (item.isFile) {
        item.file((file: File) => {
          files.push({
            file,
            path: `${path}/${file.name}`,
          });
          resolve();
        });
      } else if (item.isDirectory) {
        const dirReader = item.createReader();
        dirReader.readEntries(async (entries: any) => {
          for (let i = 0; i < entries.length; i++) {
            await traverseFileTree(entries[i], `${path}/${item.name}`);
          }
          resolve();
        }, reject);
      }
    });
  };

  if (dataTransfer && dataTransfer.items) {
    await Promise.all(
      Array.from(dataTransfer.items).map(async f => {
        const entry = f.webkitGetAsEntry();
        if (!entry) return;
        if (!entry.isFile) {
          await traverseFileTree(entry);
        } else {
          f.getAsFile() && files.push({ file: f.getAsFile()!, path: entry.fullPath });
        }
      }),
    );
  }

  return files;
};
/* 重置文件名【本地】 */
export const resetFileName = (file: File, name?: string) => {
  const fileExtension = file.name.split('.').pop();
  const randomName = `${nanoid()}${Date.now()}`;
  const newFileName = `${randomName || name}.${fileExtension}`;
  return new File([file], newFileName, { type: file.type });
};
export const blobToText = (blob: Blob): Promise<string> => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (event: ProgressEvent<FileReader>) => {
      const text = event.target?.result as string;
      resolve(text);
    };
    reader.onerror = (event: ProgressEvent<FileReader>) => {
      reject(event.target?.error);
    };
    reader.readAsText(blob);
  });
};
